package com.ruicar.afs.cloud.basic.common.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.basic.api.corporate.dto.BasicPenaltyExemptDto;
import com.ruicar.afs.cloud.basic.api.corporate.dto.PenaltyExemptDetailsDto;
import com.ruicar.afs.cloud.basic.common.entity.*;
import com.ruicar.afs.cloud.basic.common.mapper.BasicExpenseRecordMapper;
import com.ruicar.afs.cloud.basic.common.service.*;
import com.ruicar.afs.cloud.basic.proceeds.debit.service.BasicDebitRecordService;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.contract.enums.CostDetailedTypeEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.ExpenseStatusEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.FeeTypeEnum;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author: Lee
 * @date 2020-05-30 04:35:07 
 * @description 
 */
@Service
public class BasicExpenseRecordServiceImpl extends ServiceImpl<BasicExpenseRecordMapper, BasicExpenseRecord> implements BasicExpenseRecordService {

    @Autowired
    private BasicPenaltyInterestDetailsService basicPenaltyInterestDetailsService;

    @Autowired
    private BasicPenaltyInterestService basicPenaltyInterestService;

    @Autowired
    private BasicExpenseRecordDetailService basicExpenseRecordDetailService;

    @Autowired
    private BasicDebitRecordService basicDebitRecordService;
    @Autowired
    private BasicReceiptDealLineService basicReceiptDealLineService;



    @Override
    public void handleExpenseRecord(BasicReceiptDealDetails receiptDealDetails,BasicExpenseRecord expenseRecord,BigDecimal amount,Long receiptId) {

        BigDecimal takeAmount = amount;

        /**  汇总数据处理 by ZC.GUO  **/
        expenseRecord.setReceivedAmt((expenseRecord.getReceivedAmt()!=null?expenseRecord.getReceivedAmt():BigDecimal.ZERO).add(takeAmount));
        expenseRecord.setRemainingAmt(expenseRecord.getRemainingAmt().subtract(takeAmount));
        if (expenseRecord.getRemainingAmt().compareTo(BigDecimal.ZERO) <= 0){
            expenseRecord.setStatus(ExpenseStatusEnum.settle);
        }
        this.updateById(expenseRecord);
        /**  罚息处理 by ZC.GUO  **/
        if(FeeTypeEnum.penalty.equals(expenseRecord.getCostType())){
            /**  罚息明细列表 by ZC.GUO  **/
            List<BasicPenaltyInterest> penaltyInterestList = basicPenaltyInterestService.list(Wrappers.<BasicPenaltyInterest>query().lambda()
                    .eq(BasicPenaltyInterest::getContractNo,expenseRecord.getContractNo())
                    .eq(BasicPenaltyInterest::getStatus, ExpenseStatusEnum.unsettle)
                    .orderByAsc(BasicPenaltyInterest::getStartDate)
            );
            if(penaltyInterestList!=null && penaltyInterestList.size()>0){
                for (BasicPenaltyInterest penaltyInterest : penaltyInterestList){
                    if (takeAmount.compareTo(BigDecimal.ZERO)>0 && (penaltyInterest.getTotalPenalty().subtract(penaltyInterest.getReceivedAmt()).subtract(penaltyInterest.getExemptedAmt()).compareTo(BigDecimal.ZERO)>0)){

                        /**  需核销金额 by ZC.GUO  **/
                        BigDecimal needAmount = penaltyInterest.getTotalPenalty().subtract(penaltyInterest.getReceivedAmt()).subtract(penaltyInterest.getExemptedAmt());
                        if (needAmount.compareTo(takeAmount)>0){
                            needAmount = takeAmount;
                        }
                        /**  罚息明细更新 by ZC.GUO  **/
                        penaltyInterest.setReceivedAmt(penaltyInterest.getReceivedAmt().add(needAmount));
                        /**  金额已还清处理 by ZC.GUO  **/
                        if (penaltyInterest.getTotalPenalty().subtract(penaltyInterest.getReceivedAmt()).subtract(penaltyInterest.getExemptedAmt()).compareTo(BigDecimal.ZERO) <= 0){
                            penaltyInterest.setStatus(ExpenseStatusEnum.settle);
                            penaltyInterest.setCompletionDate(Calendar.getInstance().getTime());
                            penaltyInterest.setEndDate(Calendar.getInstance().getTime());
                        }
                        basicPenaltyInterestService.updateById(penaltyInterest);
                        /**  可用金额更新 by ZC.GUO  **/
                        takeAmount = takeAmount.subtract(needAmount);
                        /**  流水记录 by ZC.GUO  **/
                        BasicPenaltyInterestDetails penaltyInterestDetails = new BasicPenaltyInterestDetails();
                        penaltyInterestDetails.setContractNo(expenseRecord.getContractNo());
                        penaltyInterestDetails.setTermNo(penaltyInterest.getTermNo());
                        penaltyInterestDetails.setCostType(expenseRecord.getCostType());
                        penaltyInterestDetails.setOperateType(CostDetailedTypeEnum.arrearsEntry);
                        penaltyInterestDetails.setDate(Calendar.getInstance().getTime());
                        penaltyInterestDetails.setAmount(needAmount);
                        penaltyInterestDetails.setReceiptId(receiptId);
                        basicPenaltyInterestDetailsService.save(penaltyInterestDetails);
                        /**  记录明细流水对照 by ZC.GUO  **/
                        BasicReceiptDealLine dealLine = new BasicReceiptDealLine();
                        dealLine.setReceiptId(receiptDealDetails.getReceiptId());
                        dealLine.setDetailId(receiptDealDetails.getId());
                        dealLine.setDealTable(penaltyInterest.getClass().getAnnotation(TableName.class).value());
                        dealLine.setDealId(penaltyInterest.getId());
                        dealLine.setDealAmt(needAmount);
                        basicReceiptDealLineService.save(dealLine);
                    }
                }
            }


        }
        /**  费用处理 by ZC.GUO  **/
        else{
            /**  费用明细列表 by ZC.GUO  **/
            List<BasicExpenseRecordDetail> expenseRecordDetailList = basicExpenseRecordDetailService.list(Wrappers.<BasicExpenseRecordDetail>query().lambda()
                    .eq(BasicExpenseRecordDetail::getContractNo,expenseRecord.getContractNo())
                    .eq(BasicExpenseRecordDetail::getStatus, ExpenseStatusEnum.unsettle)
                    .eq(BasicExpenseRecordDetail::getCostType,expenseRecord.getCostType())
                    .gt(BasicExpenseRecordDetail::getRemainingAmt,BigDecimal.ZERO)
                    .orderByAsc(BasicExpenseRecordDetail::getEndDate)
            );
            if(expenseRecordDetailList!=null && expenseRecordDetailList.size()>0){
                for (BasicExpenseRecordDetail expenseRecordDetail : expenseRecordDetailList){
                    if (takeAmount.compareTo(BigDecimal.ZERO)>0){

                        /**  需核销金额 by ZC.GUO  **/
                        BigDecimal needAmount = expenseRecordDetail.getRemainingAmt();
                        if (needAmount.compareTo(takeAmount)>0){
                            needAmount = takeAmount;
                        }
                        /**  费用明细更新 by ZC.GUO  **/
                        expenseRecordDetail.setReceivedAmt(expenseRecordDetail.getReceivedAmt().add(needAmount));
                        expenseRecordDetail.setRemainingAmt(expenseRecordDetail.getRemainingAmt().subtract(needAmount));
                        /**  金额已还清处理 by ZC.GUO  **/
                        if (expenseRecordDetail.getRemainingAmt().compareTo(BigDecimal.ZERO) <= 0){
                            expenseRecordDetail.setStatus(ExpenseStatusEnum.settle);
                        }
                        basicExpenseRecordDetailService.updateById(expenseRecordDetail);
                        /**  可用金额更新 by ZC.GUO  **/
                        takeAmount = takeAmount.subtract(needAmount);
                        /**  流水记录 by ZC.GUO  **/
                        BasicPenaltyInterestDetails penaltyInterestDetails = new BasicPenaltyInterestDetails();
                        penaltyInterestDetails.setContractNo(expenseRecord.getContractNo());
                        penaltyInterestDetails.setTermNo(null);
                        penaltyInterestDetails.setCostType(expenseRecordDetail.getCostType());
                        penaltyInterestDetails.setOperateType(CostDetailedTypeEnum.arrearsEntry);
                        penaltyInterestDetails.setDate(Calendar.getInstance().getTime());
                        penaltyInterestDetails.setAmount(takeAmount);
                        basicPenaltyInterestDetailsService.save(penaltyInterestDetails);
                        /**  记录明细流水对照 by ZC.GUO  **/
                        BasicReceiptDealLine dealLine = new BasicReceiptDealLine();
                        dealLine.setReceiptId(receiptDealDetails.getReceiptId());
                        dealLine.setDetailId(receiptDealDetails.getId());
                        dealLine.setDealTable(expenseRecordDetail.getClass().getAnnotation(TableName.class).value());
                        dealLine.setDealId(expenseRecordDetail.getId());
                        dealLine.setDealAmt(needAmount);
                        basicReceiptDealLineService.save(dealLine);
                    }
                }
            }
        }
    }

    @Override
    public void cancelExpenseRecord(BasicReceiptDealDetails receiptDealDetails) {
        BigDecimal dealAmt = receiptDealDetails.getDealAmt();
        BasicExpenseRecord expenseRecord = this.getById(receiptDealDetails.getDealId());
        if (EmptyUtils.isNotEmpty(expenseRecord)){
            expenseRecord.setReceivedAmt(expenseRecord.getReceivedAmt().subtract(dealAmt));
            expenseRecord.setRemainingAmt((expenseRecord.getRemainingAmt().add(dealAmt)));
            expenseRecord.setStatus(ExpenseStatusEnum.unsettle);
            this.updateById(expenseRecord);

            /**  罚息 by ZC.GUO  **/
            if(FeeTypeEnum.penalty.equals(expenseRecord.getCostType())){
                this.cancelPenalty(receiptDealDetails.getId(),expenseRecord,receiptDealDetails.getDealAmt());
            }
            /**  其他 by ZC.GUO  **/
            else{
                this.cancelOthers(receiptDealDetails.getId(),expenseRecord,receiptDealDetails.getDealAmt());
            }
        }
    }

    @Override
    public void cancelPenalty(Long receiptDetailId,BasicExpenseRecord expenseRecord, BigDecimal dealAmt) {
        /**  罚息明细列表 by ZC.GUO  **/
        List<BasicPenaltyInterest> penaltyInterestList = basicPenaltyInterestService.list(Wrappers.<BasicPenaltyInterest>query().lambda()
                .eq(BasicPenaltyInterest::getContractNo,expenseRecord.getContractNo())
                .orderByDesc(BasicPenaltyInterest::getStartDate)
        );
        if (EmptyUtils.isNotEmpty(penaltyInterestList)){
            for (BasicPenaltyInterest penaltyInterest : penaltyInterestList){
                BasicReceiptDealLine dealLine = basicReceiptDealLineService.getOne(Wrappers.<BasicReceiptDealLine>query().lambda()
                        .eq(BasicReceiptDealLine::getDetailId,receiptDetailId)
                        .eq(BasicReceiptDealLine::getDealId,penaltyInterest.getId())
                        .eq(BasicReceiptDealLine::getDealTable,penaltyInterest.getClass().getAnnotation(TableName.class).value())
                );
                if (EmptyUtils.isNotEmpty(dealLine) && dealLine.getDealAmt().compareTo(BigDecimal.ZERO)>0){
                    /**  最多可撤销金额金额 by ZC.GUO  **/
                    BigDecimal needAmount = dealLine.getDealAmt();
                    penaltyInterest.setReceivedAmt(penaltyInterest.getReceivedAmt().subtract(needAmount));
                    penaltyInterest.setStatus(ExpenseStatusEnum.unsettle);
                    penaltyInterest.setCompletionDate(null);
                    penaltyInterest.setEndDate(null);
                    basicPenaltyInterestService.updateById(penaltyInterest);
                }
            }
        }

        /**  流水记录 by ZC.GUO  **/
        BasicPenaltyInterestDetails penaltyInterestDetails = new BasicPenaltyInterestDetails();
        penaltyInterestDetails.setContractNo(expenseRecord.getContractNo());
        penaltyInterestDetails.setTermNo(null);
        penaltyInterestDetails.setCostType(expenseRecord.getCostType());
        penaltyInterestDetails.setOperateType(CostDetailedTypeEnum.cancelEntry);
        penaltyInterestDetails.setDate(Calendar.getInstance().getTime());
        penaltyInterestDetails.setAmount(dealAmt);
        basicPenaltyInterestDetailsService.save(penaltyInterestDetails);
    }

    @Override
    public void cancelOthers(Long receiptDetailId,BasicExpenseRecord expenseRecord, BigDecimal dealAmt) {
        /**  费用明细列表 by ZC.GUO  **/
        List<BasicExpenseRecordDetail> expenseRecordDetailList = basicExpenseRecordDetailService.list(Wrappers.<BasicExpenseRecordDetail>query().lambda()
                .eq(BasicExpenseRecordDetail::getContractNo,expenseRecord.getContractNo())
                .orderByDesc(BasicExpenseRecordDetail::getCreateTime)
        );
        if (EmptyUtils.isNotEmpty(expenseRecordDetailList)){
            for (BasicExpenseRecordDetail expenseRecordDetail : expenseRecordDetailList){
                BasicReceiptDealLine dealLine = basicReceiptDealLineService.getOne(Wrappers.<BasicReceiptDealLine>query().lambda()
                        .eq(BasicReceiptDealLine::getDetailId,receiptDetailId)
                        .eq(BasicReceiptDealLine::getDealId,expenseRecordDetail.getId())
                        .eq(BasicReceiptDealLine::getDealTable,expenseRecordDetail.getClass().getAnnotation(TableName.class).value())
                );
                if (EmptyUtils.isNotEmpty(dealLine) && dealLine.getDealAmt().compareTo(BigDecimal.ZERO)>0){
                    /**  最多可撤销金额金额 by ZC.GUO  **/
                    BigDecimal needAmount = dealLine.getDealAmt();
                    expenseRecordDetail.setReceivedAmt(expenseRecordDetail.getReceivedAmt().subtract(needAmount));
                    expenseRecordDetail.setRemainingAmt(expenseRecordDetail.getRemainingAmt().add(needAmount));
                    expenseRecordDetail.setStatus(ExpenseStatusEnum.unsettle);
                    expenseRecordDetail.setEndDate(null);
                    basicExpenseRecordDetailService.updateById(expenseRecordDetail);
                }
            }
        }
        /**  流水记录 by ZC.GUO  **/
        BasicPenaltyInterestDetails penaltyInterestDetails = new BasicPenaltyInterestDetails();
        penaltyInterestDetails.setContractNo(expenseRecord.getContractNo());
        penaltyInterestDetails.setTermNo(null);
        penaltyInterestDetails.setCostType(expenseRecord.getCostType());
        penaltyInterestDetails.setOperateType(CostDetailedTypeEnum.cancelEntry);
        penaltyInterestDetails.setDate(Calendar.getInstance().getTime());
        penaltyInterestDetails.setAmount(dealAmt);
        basicPenaltyInterestDetailsService.save(penaltyInterestDetails);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResponse updatePenaltyInterest(BasicPenaltyExemptDto condition, Date batchDate) {
        BigDecimal b = BigDecimal.valueOf(0);

        //更新合同费用记录
        BasicExpenseRecord basicExpenseRecord = this.getOne(Wrappers.<BasicExpenseRecord>lambdaQuery()
                .eq(BasicExpenseRecord::getContractNo, condition.getContractNo())
                .eq(BasicExpenseRecord::getCostType, FeeTypeEnum.penalty));
        if (basicExpenseRecord != null) {
            basicExpenseRecord.setExemptedAmt(basicExpenseRecord.getExemptedAmt().add(condition.getExemptionAmt()));
            basicExpenseRecord.setExemptionAmt(basicExpenseRecord.getExemptionAmt().add(condition.getExemptionAmt()));
            basicExpenseRecord.setRemainingAmt(basicExpenseRecord.getCostAmt().subtract(basicExpenseRecord.getReceivedAmt().add(basicExpenseRecord.getExemptionAmt())));
            if (basicExpenseRecord.getRemainingAmt().compareTo(b) <= 0) {
                basicExpenseRecord.setStatus(ExpenseStatusEnum.settle);
            }
            this.updateById(basicExpenseRecord);
        }


        for (PenaltyExemptDetailsDto penaltyInterest : condition.getManagePenaltyExemptDetails()) {
            if (penaltyInterest.getExemptionAmt().compareTo(b) != 0 || ExpenseStatusEnum.settle.equals(penaltyInterest.getStatus())) {
                //更新合同费用流水明细表
                BasicPenaltyInterestDetails penaltyInterestDetails = new BasicPenaltyInterestDetails();
                penaltyInterestDetails.setContractNo(penaltyInterest.getContractNo());
                penaltyInterestDetails.setAmount(penaltyInterest.getExemptionAmt());
                penaltyInterestDetails.setTermNo(penaltyInterest.getTermNo());
                penaltyInterestDetails.setCostType(FeeTypeEnum.penalty);
                penaltyInterestDetails.setOperateType(CostDetailedTypeEnum.arrearsExempt);
                penaltyInterestDetails.setDate(DateUtil.date());
                basicPenaltyInterestDetailsService.save(penaltyInterestDetails);
                //更新合同每期罚息明细
                BasicPenaltyInterest basicPenaltyInterest = basicPenaltyInterestService.getOne(Wrappers.<BasicPenaltyInterest>lambdaQuery().
                        eq(BasicPenaltyInterest::getContractNo, penaltyInterest.getContractNo())
                        .eq(BasicPenaltyInterest::getTermNo, penaltyInterest.getTermNo()));
                basicPenaltyInterest.setExemptedAmt(basicPenaltyInterest.getExemptedAmt().add(penaltyInterest.getExemptionAmt()));
                basicPenaltyInterest.setRealExemptionAmt(basicPenaltyInterest.getRealExemptionAmt().add(penaltyInterest.getExemptionAmt()));
                if (basicPenaltyInterest.getTotalPenalty().subtract(basicPenaltyInterest.getReceivedAmt().add(basicPenaltyInterest.getExemptedAmt())).compareTo(b) == 0) {
                    basicPenaltyInterest.setStatus(ExpenseStatusEnum.settle);
                }
                basicPenaltyInterestService.updateById(basicPenaltyInterest);
            }
        }
        basicDebitRecordService.addDebitRecordList(condition.getContractNo(),batchDate);
        return new IResponse().setData(true);
    }
}
